/* 
 * File:   Renderer.h
 * Author: johannes
 *
 * Created on January 4, 2014, 7:19 PM
 */

#ifndef RENDERER_H
#define	RENDERER_H

#include <SDL2/SDL.h>
#include <map>
#include "Utility.h"


namespace GUL {
    namespace System {
        namespace Graphic {
            class Surface;
            class Texture;
            class Window;

            class Renderer {
            private:
                SDL_Renderer* m_Renderer;
                Textures m_TextureDictionary;

                SDL_Texture* SDLCreateTexture(UPair& Boundary, Uint32 format, int access);
                SDL_Texture* SDLCreateTexture(Surface&);
                SDL_Texture* SDLCreateTexture(SDL_Surface*);
            protected:

                void insertTexture(const std::string& name, Texture*);

                Renderer(Renderer&);

            public:

                Renderer();
                Renderer(Window&, Uint32);
                Renderer(Window&, int, Uint32);
                Renderer(Surface&);
                virtual ~Renderer();


                SDL_RendererInfo* Information();
                UPair OutputSize();

                Texture& CreateTexture(const std::string& name, UPair& Boundary, Uint32 format, int access);
                Texture& CreateTexture(const std::string& name, Surface&);
                Texture& CreateTexture(const std::string& name, SDL_Surface*);

                Texture& RenderTarget();
                void RenderTarget(Texture&);
                void RenderTarget(void* a=nullptr);
                void RenderCopy(Texture&, const SDL_Rect*src, const SDL_Rect* dst);
                void RenderCopyEx(Texture&,const SDL_Rect*,const SDL_Rect*,const double,const IPair&,const SDL_RendererFlip);
                
                void ReadPixelFromTarget(const SDL_Rect*,Uint32,void*,int);
                
                
                void LogicalSize(UPair& Boundary);
                UPair& LogicalSize();

                void Viewport(const SDL_Rect*);
                SDL_Rect* Viewport();

                void ClipRect(const SDL_Rect*);
                SDL_Rect* ClipRect() const;

                void Scale(float scaleX, float scaleY);
                void Scale(float* scaleX,float* scaleY);

                void DrawColor(SDL_Colour);
                SDL_Colour& DrawColor() const;

                void DrawBlendMode(SDL_BlendMode);
                SDL_BlendMode DrawBlendMode() const;

                void Clear();
                void Present();

                void DrawPoint(IPair position);
                void DrawPoints(const std::vector<IPair>&);
                
                void DrawLine(IPair pos1, IPair pos2);
                void DrawLines(const std::vector<IPair>&);
                
                void DrawRect(const SDL_Rect*);
                void DrawRects(const std::vector<Rect>&);
                void FillRect(const SDL_Rect*);
                void FillRects(const std::vector<Rect>&);
                
                SDL_Renderer*           GetRenderer();
                bool                    RenderTargetSupported();
                
                
                int GL_BindTexture(const std::string&,float* texw,float* texh);
                int GL_UnbindTexture(const std::string&);

                inline operator SDL_Renderer*() {
                    return this->m_Renderer;
                }
                Texture& operator[](const std::string& index);

                friend class Texture;
            };
        }
    }

}
#endif	/* RENDERER_H */

